package com.epi.one.main;

import com.epi.one.basic.generic.GenericExample;
import com.epi.one.basic.generic.TypeExample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.*;
import java.nio.charset.Charset;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.concurrent.*;

/**
 * @author dxy
 * @version 1.0
 */
public class TypeDemo {
    public static void main(String[] args) {
        test();
    }

    public static void test() {
        printClass( GenericExample.class);
        printTypeExample();
    }

    private static void printTypeExample() {
        Field[] fields = TypeExample.class.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("Field: " + field.getName());
            Type type = field.getGenericType();
            printType(type);
            if (type instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) type;
                Type[] args = pt.getActualTypeArguments();
                System.out.println("  --------------> Inspecting");
                for (Type arg : args) {
                    printType(arg); // 💡 此时将触发 WildcardType 分支
                }
                System.out.println("  --------------> Done");
            }
            System.out.println();
        }
    }

    private static void printClass(Class<?> cl) {
        System.out.println("Class: " + cl.getName());

        // 泛型参数
        TypeVariable<? extends Class<?>>[] typeParameters = cl.getTypeParameters();
        System.out.println("Type Parameters:");
        for (TypeVariable<? extends Class<?>> tp : typeParameters) {
            System.out.println("  Name: " + tp.getName());
            System.out.println("  Bounds: " + Arrays.toString(tp.getBounds()));
        }

        // 泛型接口
        Type[] genericInterfaces = cl.getGenericInterfaces();
        System.out.println("Generic Interfaces:");
        printTypes(genericInterfaces);

        // 泛型父类
        Type genericSuperclass = cl.getGenericSuperclass();
        System.out.println("Generic Superclass:");
        printType(genericSuperclass);

        // 打印所有方法及其泛型信息
        System.out.println("Methods:");
        Method[] methods = cl.getDeclaredMethods();
        for (Method m : methods) {
            printMethod(m);
        }

    }

    private static void printTypes(Type[] types) {
        if (types == null || types.length == 0) {
            System.out.println("  <none>");
            return;
        }
        for (Type t : types) {
            printType(t);
        }
    }

    private static void printType(Type t) {
        if (t instanceof ParameterizedType) { //带有实际类型参数的泛型 如 List<String>
            ParameterizedType pt = (ParameterizedType) t;
            System.out.println("  ParameterizedType: " + pt.getRawType());
            System.out.println("    Actual Type Arguments: " + Arrays.toString(pt.getActualTypeArguments()));
            System.out.println("    Owner Type: " + pt.getOwnerType());
        } else if (t instanceof TypeVariable) {  //类型变量（如 <T>
            TypeVariable<?> tv = (TypeVariable<?>) t;
            System.out.println("  TypeVariable: " + tv.getName());
            System.out.println("    Bounds: " + Arrays.toString(tv.getBounds()));
        } else if (t instanceof WildcardType) { // 通配符（如 ? extends Number）
            WildcardType wt = (WildcardType) t;
            System.out.println("  WildcardType:");
            System.out.println("    Upper Bounds: " + Arrays.toString(wt.getUpperBounds()));
            System.out.println("    Lower Bounds: " + Arrays.toString(wt.getLowerBounds()));
        } else if (t instanceof Class) {
            Class<?> c = (Class<?>) t;
            System.out.println("  Class: " + c.getName());
        } else if(t instanceof GenericArrayType) {
            GenericArrayType gt = (GenericArrayType) t;
            System.out.println("  GenericArrayType: " + gt.getGenericComponentType());
        }
        else {
            System.out.println("  Unknown Type: " + t);
        }
    }

    private static void printMethod(Method m) {
        System.out.println("Method: " + m.getName());

        // 泛型类型参数
        TypeVariable<Method>[] typeParams = m.getTypeParameters();
        if (typeParams.length > 0) {
            System.out.println("  Type Parameters:");
            for (TypeVariable<Method> tp : typeParams) {
                System.out.println("    Name: " + tp.getName());
                System.out.println("    Bounds: " + Arrays.toString(tp.getBounds()));
            }
        }

        // 参数类型
        Type[] paramTypes = m.getGenericParameterTypes();
        System.out.println("  Parameter Types:");
        for (Type pt : paramTypes) {
            System.out.println("    " + pt.getTypeName());
        }

        // 返回类型
        Type returnType = m.getGenericReturnType();
        System.out.println("  Return Type: " + returnType.getTypeName());
        System.out.println();
    }

    public static class ThreadDemo {

        private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");

        public static void main(String[] args) throws Exception {
    //        allOf();
    //        exceptionThen();
    //        processTask();
    //        interruptThread();
    //        yieldThread();
    //        guardThread();
        }

        private static void guardThread() {
            Thread daemonThread = new Thread(() -> {
                while (true) {
                    System.out.println("Daemon thread is running...");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        System.out.println("Daemon interrupted");
                        break;
                    }
                }
            });
    //        daemonThread.setDaemon(true);  // 设置为守护线程
            daemonThread.start();

            // 主线程只运行3秒
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) { }

            System.out.println("Main thread ends.");
            // JVM退出，守护线程随之结束
        }

        private static void yieldThread() {
            Thread t1 = new Thread(() -> {
                for (int i = 0; i < 50; i++) {
                    Thread.yield();  // 让出CPU，给同优先级线程机会
                    System.out.println(Thread.currentThread().getName() + " " + i);
                    Thread.yield();  // 让出CPU，给同优先级线程机会
                }
            },"A");
            Thread t2 = new Thread(() -> {
                for (int i = 0; i < 50; i++) {
                    System.out.println(Thread.currentThread().getName() + " " + i);

                }
            },"BBBBBB");

            t1.start();
            t2.start();
        }

        private static void interruptThread() throws InterruptedException {
            Thread t = new Thread(() -> {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println("Working...");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        System.out.println("Sleep interrupted");
                        Thread.currentThread().interrupt();  // 重新设置中断标志
                    }
                }
                System.out.println("Thread detected interrupt, exiting...");
            });

            t.start();
            Thread.sleep(3000);
            t.interrupt(); // 主线程中断子线程
        }

        private static void processTask() throws IOException {
            ProcessBuilder pb = new ProcessBuilder("ping", "www.baidu.com");
            Process process = pb.start();
            ProcessHandle handle = process.toHandle();
            InputStream processOut = process.getInputStream();  // 标准输出
            InputStream processErr = process.getErrorStream();  // 错误输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(processOut, Charset.forName("GBK")));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("OUTPUT: " + line);
            }
            System.out.println("PID: " + handle.pid());
            handle.onExit().thenRun(() -> System.out.println("Process finished."));
        }

        private static void exceptionThen() {
            CompletableFuture<String> cf = CompletableFuture
                .supplyAsync(() -> {
                    try {
                        System.out.println("Sleep");
                        Thread.sleep(3000L);
                        System.out.println("Sleep over");
                        throw new RuntimeException(new ArithmeticException());
                    } catch (InterruptedException e) {
                        System.out.println("interrupted");
                        Thread.currentThread().interrupt();
                    }
                    return "hello";
                })
                .exceptionally(Throwable::getMessage)
    //            .thenRun(()->{
    //                System.out.println("Run over");
    //            })
                .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + "      456"));
            cf.thenAccept(System.out::println);
            cf.join();
        }

        private static void allOf() {
            CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
                log("f1 started");
                try {
                    Thread.sleep(4000); // 模拟耗时
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                log("f1 finished");
                return "A";
            });
            CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
                log("f2 started");
                try {
                    Thread.sleep(1000); // 模拟耗时
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                log("f2 finished");
                return "B";
            });
            log("Main thread waiting for all...");
            CompletableFuture.allOf(f1, f2).join(); // 等两个都完成
            log("All tasks completed");
            System.out.println("A: " + f1.join());
            System.out.println("B: " + f2.join());
        }

        private static void log(String message) {
            System.out.printf("[%s] [%s] %s%n",
                formatter.format(LocalTime.now()),
                Thread.currentThread().getName(),
                message);
        }
    }
}
